
;*******************************************************
;
;	SCSI Driver Main Driver.
;
;	Written by Matt Gulick.		Started May 16,1988
;
;	Copyright Apple Computer, Inc. 1988-90
;
;*******************************************************

;*******************************************************
;
;	This file contains the code segment that is called
;	when a Device call comes in.  This code is
;	responsible for checking the validity of the
;	command, setting the environment and parsing the
;	call to the desired filter.
;
;*******************************************************

;*******************************************************
;
;	Revision History:
;
;*******************************************************

;	May 16, 1988	File started.
;	May 17,	1988	DIB Record defined.
;	June 6,	1988	Main Driver Written.
;	Jun	10,	1988	Broke down files into links.
;	Jun	20,	1988	Add comments concerning Registers to the
;					routine headers.  Also incorporate
;					changes from code review.
;	July 8,	1988	Added code to allocate Directpage area
;					of $100 bytes.
;	Oct 25,	1988	Modified the default DIB to reflect the
;					changes in the SCSI Manager Interface.
;					Also made changes in the code to account
;					for this.
;
;	Apr	10,	1989	Started code for character devices.
;

				STRING		PASCAL
				BLANKS		OFF
				PAGESIZE	70
				PRINT		NOGEN
				PRINT		NOMDIR
				MACHINE		M65816

				IMPORT		startup
				IMPORT		Open
				IMPORT		Read
				IMPORT		Write
				IMPORT		Close
				IMPORT		Status
				IMPORT		Control
				IMPORT		Flush
				IMPORT		Shutdown
				IMPORT		g_dib_ptr

				ENTRY		default_dib
				ENTRY		direct_page		;Driver Mgmt
				ENTRY		exit_dpage		;Driver Mgmt
				ENTRY		gsos_dpage		;Driver Mgmt
				ENTRY		lst_rslt_ec		;Status
				ENTRY		lst_rslt_id
				ENTRY		lst_rslt_stat
				ENTRY		lst_rslt_skey
				ENTRY		lst_rslt_info
				ENTRY		lst_rslt_rqlen
				ENTRY		lst_rslt_scode
				ENTRY		auto_sense_data	;Main Driver

				EJECT

				INCLUDE		'scsihd.equates'

				PRINT		OFF
				INCLUDE		'M16.MEMORY'
				INCLUDE		'M16.UTIL'
				PRINT		ON
			
;*******************************************************
;
;	This dummy Procedure is used to inform the loader.
;	Drivers start with data but are not data segments.
;	The loader may load what it thinks to be a data
;	segment accross bank boundries.  This is not good
;	for code.
;
;*******************************************************

				EXPORT	dummy
dummy			PROC
				ENDP
			
;*******************************************************
;
;	Header as required by the device dispatcher for
;	drivers.
;
;*******************************************************

				EXPORT	start
start			PROC

				dc.w	default_dib-start
				dc.w	$0001
				dc.w	ctrl_list-start
				
ctrl_list		dc.l	null
				dc.l	null

				ENDP
			
;*******************************************************
;
;	Main entry to the SCSI Driver code segment.  The
;	state of the machine at this point is:
;
;		Acc				=	Call Number
;					$0000	=	Startup
;					$0001	=	Open
;					$0002	=	Read
;					$0003	=	Write
;					$0004	=	Close
;					$0005	=	Status
;					$0006	=	Control
;					$0007	=	Flush
;					$0008	=	Shutdown
;		Y register		=	Unspecified
;		X register		=	Unspecified
;		P register		=	0=M=X=e
;		Direct Page		=	GS/OS Direct Page
;		Data Bank		=	Unspecified
;		Stack Pointer	=	GS/OS Stack
;		System Speed	=	Fast
;
;*******************************************************

				EXPORT	drvr_main
drvr_main		PROC
										;
										; Preserve Callers Data Bank
										; and set ours.
										;
				phb
				phk
				plb
										;
										; Check to see if we have our own
										; Direct Page. If so then copy first
										; 'x' bytes to our temp, switch DP and
										; copy it back to ours.
										;
				ldx		|direct_page
				beq		@chk_startup	;No DP. This must be a startup call.
										;
										; Set our Direct Page with the first
										; 'x' Bytes equal to the GS/OS DP
										; settings.
										;
				pha
										;
				clc						; Calculate Source Address of GS/OS
				tdc						; Direct Page that we want.
				sta		|gsos_dpage		; Preserving GS/OS DP for later use.
				adc		#dev_num
				pea		$0000
				pha
										;
				clc						; Calculate Destination Address of
				lda		|direct_page	; our Direct Page that we want.
				adc		#dev_num
				pea		$0000
				pha
				
				pushlong	#dib_ptr+4	;Length of the move
				
				pushword	#move_sinc_dinc

				jsl		move_info		;Move the data
										;
										; Set our Direct Page.
										;
				lda		|direct_page
				tcd
										;
										; Continue with call.
										;
				pla
				bra		@do_command
										;
										; Validate for Startup Command.
										;
@chk_startup	cmp		#cmd_start
				bne		@error1
										;
										; Convert call number in Acc
										; to an index into our jmp table
										;
@do_command		cmp		#max_d_cmd+1
				bge		@error
@do_cmd1		asl		a
				tax
										;
										; If this is a status call $0005
										; then don't clear these values.
										; That's what they are trying to
										; get.
										;
				cmp		#cmd_status*2	;Account for the ASL
				bne		@clear			;Not a status call
				lda		<stat_code		;Is it Code $0005?
				cmp		#$0005
				beq		@dont_clear		;Yes. Skip the clear code.
										;
										; Clear the data from the last call.
										;
@clear			lda		<dev_num
				sta		|lst_rslt_id
										;
										; Check to see if device is still
										; performing the last call isued.
										;
@dont_clear		ldy		#dib.dvcflag
				lda		[dib_ptr],y
				and		#int_busy
				beq		@do_call
										;
										; Still Busy.  Return Busy Error.
										;
				lda		|gsos_dpage
				tcd

				lda		#drvr_busy
				bra		@error2

@do_call		jsr		(@table,x)
										;
										; Clean Exit.
										;
										; Get our Direct Page with the first
										; 'x' Bytes equal to the GS/OS DP
										; settings and return them.
										;
				pha
				php
										;
										; Check to see if premature termination.
										;
				lda		|exit_dpage
				beq		@purge_me		;Hurt Me! I Like it.
										;
										; No. Then Return Control of the
										; Direct Page back to GS/OS.
										;
				clc						; Calculate Source Address of
				adc		#dev_num		; our Direct Page that we used.
				pea		$0000
				pha

				clc						; Calculate Destination Address of
				lda		|gsos_dpage		; GS/OS Direct Page.
				tcd						; Resetting it also at this time.
				adc		#dev_num		; Preserving GS/OS DP for later use.
				pea		$0000
				pha
				
				pushlong	#dib_ptr	;Length of the move
				
				pushword	#move_sinc_dinc

				jsl		move_info		;Return the data

										;
										; If Direct_page = 0 then this is
										; the final exit and we need to also
										; zero out the exit_dpage value.
										;
				lda		|direct_page
				bne		@purge_me
				stz		|exit_dpage

@purge_me		plp
				pla
				plb
				bcs		@yes_error
				lda		#null
@yes_error		rtl
										;
										; Error Exit
										;
										; Reset GS/OS Direct Page.
										;
@error			lda		|gsos_dpage
				tcd
@error1			lda		#drvr_bad_code
@error2			sec
				plb
										;
										; Save Error Code for Get Last
										; Result Call
										;
				sta		|lst_rslt_ec
				rtl
			
;*******************************************************
;
;	Jump table and code.
;
;*******************************************************

@table			dc.w	startup
				dc.w	Open
				dc.w	Read
				dc.w	Write
				dc.w	Close
				dc.w	Status
				dc.w	Control
				dc.w	Flush
				dc.w	Shutdown


				EJECT
										;
										; Dispatcher Routing routine
										;
				EXPORT	rout2_s_disp
rout2_s_disp	pha

				lda		|direct_page	;If this is the first time, then
				bne		@use_ours

				pla
				jsl		s_dispatch
				rts

@use_ours		lda		|gsos_dpage
				tcd
				pla
				jsl		s_dispatch
				pha
				lda		|direct_page
				tcd
				pla
				rts

				ENDP

				EJECT
			
;*******************************************************
;
;	The following statements are used to define the DIB
;	structure.  The structure contains the traditional
;	DIB followed by an extension used for device
;	maintainence.  All together each DIB with the
;	associated extensions will take one page of RAM.
;
;*******************************************************
;
;	$00	------------------------------------------------
;		|											   |
;		|      Device Information Block Data (DIB)     |
;	$3F	|											   |
;		------------------------------------------------
;	$40	|             Physical Block Number            |
;		|											   |
;	$43	|        that maps to logical block zero       |
;		------------------------------------------------
;	$44	|											   |
;		|                 Head Pointer                 |
;	$47	|											   |
;		------------------------------------------------
;	$48	|											   |
;		|               Forward Pointer                |
;	$4B	|											   |
;		------------------------------------------------
;	$4C	|				Memory DIB Count			   |
;		------------------------------------------------
;	$4E	|			Partition Map Block Number		   |
;		------------------------------------------------
;	$50	|											   |
;		|      Memory Manager Handle for this DIB      |
;	$53	|											   |
;		------------------------------------------------
;	$54	|											   |
;		|              Block Size (Bytes)              |
;	$57	|											   |
;		------------------------------------------------
;	$58	|       Max SCSI Command for this Device       |
;		------------------------------------------------
;	$5A	|                                              |
;		|   Command Bitmap (See ERS for description)   |
;	$79	|                                              |
;		------------------------------------------------
;	$7A	|              SCSI Command Data               |
;		|                     and                      |
;	$D9	|      SCSI Manager Call Buffer Structures     |
;		------------------------------------------------
;	$DA	|            'Busy' and other Flags            |
;		------------------------------------------------
;	$DC	|                                              |
;		|          Completion Vector with Code         |
;	$FF	|                                              |
;		------------------------------------------------
;
;*******************************************************

			EXPORT	default_dib
default_dib	PROC
									;
									; Definition of DIB Structure.
									;
			dc.l	$00000000		; DIB Link Pointer				(LONG)
			dc.l	drvr_main		; Pointer to Drvrs Main Entry	(LONG)

;-------------------------------------------------------------------------------

			IF		scsi_dtype = direct_acc	THEN

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

			IF		warm_ss_suprt = true		THEN

			dc.w	restartable++\	;Restartable from ram	if Set	(WORD)
					speed_ind++\	;Device is speed ind	if Set
					blk_device++\	;Block Device			if Set
					write_allow++\	;Write is Allowed		if Set
					read_allow++\	;Read is Allowed		if Set
					format_allow	;Format is Allowed		if Set

			ELSE

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

			dc.w	speed_ind++\	;Device is speed ind	if Set	(WORD)
					blk_device++\	;Block Device			if Set
					write_allow++\	;Write is Allowed		if Set
					read_allow++\	;Read is Allowed		if Set
					format_allow	;Format is Allowed		if Set

			ENDIF

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

			ENDIF

;-------------------------------------------------------------------------------

									;
									; Is it a Write-once Read-multiple Device.
									;
			IF		scsi_dtype = apple_cd	THEN

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

			IF		warm_ss_suprt = true		THEN

			dc.w	restartable++\	;Restartable from ram	if Set	(WORD)
					speed_ind++\	;Device is speed ind	if Set
					blk_device++\	;Block Device			if Set
					read_allow		;Read is Allowed		if Set

			ELSE

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

			dc.w	speed_ind++\	;Device is speed ind	if Set	(WORD)
					blk_device++\	;Block Device			if Set
					read_allow		;Read is Allowed		if Set

			ENDIF

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

			ENDIF

;-------------------------------------------------------------------------------

									;
									; Is it an MCD 40 Tape Drive
									;
			IF		scsi_dtype = mcd_40	THEN

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

			IF		warm_ss_suprt = true		THEN

			dc.w	restartable++\	;Restartable from ram	if Set	(WORD)
					speed_ind++\	;Device is speed ind	if Set
					blk_device++\	;Block Device			if Set
					write_allow++\	;Write is Allowed		if Set
					read_allow++\	;Read is Allowed		if Set
					format_allow	;Format is Allowed		if Set

			ELSE

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

			dc.w	speed_ind++\	;Device is speed ind	if Set	(WORD)
					blk_device++\	;Block Device			if Set
					write_allow++\	;Write is Allowed		if Set
					read_allow++\	;Read is Allowed		if Set
					format_allow	;Format is Allowed		if Set

			ENDIF

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

 			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = scanner	THEN
									;
									; Is it a Scanner Device?
									;
			dc.w	speed_ind++\	;Device is speed ind	if Set
					read_allow		;Read is Allowed		if Set

 			ENDIF

;-------------------------------------------------------------------------------

			dc.l	$00000000		; Block Count for this device	(LONG)
									; Set to default. This can change
									;
									; Length of Descriptive Name	(PSTR)
									; Followed by the Descriptive
									; Name for the device.  This
									; is a conditional Assembly.
									;

;-------------------------------------------------------------------------------

			IF		scsi_dtype = direct_acc	THEN
									;
									; Is it a Direct-Access Device.
									;
			dc.b	'SCSIHD.00.00'
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = seq_acc	THEN
									;
									; Is it a Sequential-Access Device.
									;
			dc.b	'SCSITAPE.00.00'
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = print_dvc	THEN
									;
									; Is it a Printer Device.
									;
			dc.b	'SCSIPRINTER.00.00'
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = proc_dvc	THEN
									;
									; Is it a Processor Device.
									;
			dc.b	'SCSIPROC.00.00'
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = worm_dvc	THEN
									;
									; Is it a Write-once Read-multiple Device.
									;
			dc.b	'SCSIWORM.00.00'
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = read_dacc	THEN
									;
									; Is it a Read-only Direct-Access Device.
									;
			dc.b	'SCSICDROM.00.00'
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = scanner	THEN
									;
									; Is it a Scanner Device.
									;
			dc.b	'SCSISCANNER.00.00'
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = optic_mem	THEN
									;
									; Is it a Optical Memory Device.
									;
			dc.b	'SCSIOPTICAL.00.00'
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = changer	THEN
									;
									; Is it a Changer Device.
									;
			dc.b	'SCSICHANGER.00.00'
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = comm_dvc	THEN
									;
									; Is it a Communication Device.
									;
			dc.b	'SCSICOM.00.00'
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = mcd_40	THEN
									;
									; Is it a Direct Access Magnetic
									; Tape Device.
									;
			dc.b	'SCSITAPE.00.00'
			ENDIF

;-------------------------------------------------------------------------------

									;
									; Pad space to fill gap to next field.
									;
			dcb.b	dib.slotnum+default_dib-*,$20
			
			dc.w	$8000			; Device Slot Number from MGR.	(WORD)
									; By setting bit 15 in the slot
									; number we can force the device
									; dispatcher to keep it around.
									; We will save this as a default
									; dib.  This will also allow us
									; to remain loaded if there are
									; no devices available at boot
									; time.
									;
			dc.w	$0000			; Device Unit Number from MGR.	(WORD)
			dc.w	drvr_vers		; Version Number for our Driver	(WORD)

;-------------------------------------------------------------------------------

			IF		scsi_dtype = direct_acc	THEN
			dc.w	$0005			; ID of Device we talk to		(WORD)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = apple_cd	THEN
			dc.w	$0007			; ID of Device we talk to		(WORD)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = mcd_40	THEN
			dc.w	$0006			; ID of Device we talk to		(WORD)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = scanner	THEN
			dc.w	$001A			; ID of Device we talk to		(WORD)
			ENDIF

;-------------------------------------------------------------------------------

			dc.w	$0000			; Head Device Link				(WORD)
			dc.w	$0000			; Forward Device Link			(WORD)
									;
									; Pointer to DIB Extension		(LONG)
									;
			dc.l	dib.start_blk+default_dib
			
			dc.w	$0000			; DIB Device Number				(WORD)
									;
									; The Starting Block Number for this device
									; is maintained here.  This is used to
									; modify the requested block number from
									; a logical to a physical number.
									;
			dc.l	$00000000		; Starting Physical Block Num.	(LONG)
									;
									; These two pointers are the compliment
									; to the links in the standard DIB and
									; will point to the actual DIB referenced
									; in the Head and Forward Device Links.
									;
			dc.l	null			; Head Dvc Pointer				(LONG)
			dc.l	null			; Forward Dvc Pointer			(LONG)
			dc.w	null			; Number of active dibs in mem	(WORD)
			dc.w	null			; Reserved						(WORD)
									;
									; Memory Manager Handle
									;
			dc.l	$00000000		;								(LONG)
									;
									; Block Size
									;
			dc.l	block_size		;								(LONG)
									;
									; Maximum SCSI Command supported by
									; the device for this DIB.
									;
			dc.w	$00FF			;								(WORD)
									;
									; SCSI Command Group Bitmaps used as defaults
									; when device does not return this info in the
									; INQUIRY Command.
									;

;-------------------------------------------------------------------------------

			IF		scsi_dtype = direct_acc	THEN
									;
									; It is a Direct-Access Device.
									;
			dc.B	$D9,$B0,$27,$BE	; Group 0						(LONG)
			dc.B	$04,$03,$1E,$FB	; Group 1						(LONG)
			dc.B	$00,$00,$04,$21	; Group 2						(LONG)
			dc.B	$00,$00,$00,$00	; Group 3						(LONG)
			dc.B	$00,$00,$00,$00	; Group 4						(LONG)
			dc.B	$00,$00,$00,$00	; Group 5						(LONG)
			dc.B	$00,$00,$00,$00	; Group 6						(LONG)
			dc.B	$00,$00,$00,$00	; Group 7						(LONG)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = seq_acc	THEN
									;
									; It is a Sequential-Access Device.
									;
			dc.B	$D4,$B1,$FF,$FF	; Group 0						(LONG)
			dc.B	$00,$10,$08,$78	; Group 1						(LONG)
			dc.B	$00,$00,$04,$21	; Group 2						(LONG)
			dc.B	$00,$00,$00,$00	; Group 3						(LONG)
			dc.B	$00,$00,$00,$00	; Group 4						(LONG)
			dc.B	$00,$00,$00,$00	; Group 5						(LONG)
			dc.B	$00,$00,$00,$00	; Group 6						(LONG)
			dc.B	$00,$00,$00,$00	; Group 7						(LONG)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = print_dvc	THEN
									;
									; It is a Printer Device.
									;
			dc.B	$98,$30,$AF,$9C	; Group 0						(LONG)
			dc.B	$00,$00,$00,$00	; Group 1						(LONG)
			dc.B	$00,$00,$04,$21	; Group 2						(LONG)
			dc.B	$00,$00,$00,$00	; Group 3						(LONG)
			dc.B	$00,$00,$00,$00	; Group 4						(LONG)
			dc.B	$00,$00,$00,$00	; Group 5						(LONG)
			dc.B	$00,$00,$00,$00	; Group 6						(LONG)
			dc.B	$00,$00,$00,$00	; Group 7						(LONG)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = proc_dvc	THEN
									;
									; It is a Processor Device.
									;
			dc.B	$90,$A0,$20,$8C	; Group 0						(LONG)
			dc.B	$00,$00,$00,$00	; Group 1						(LONG)
			dc.B	$00,$00,$04,$21	; Group 2						(LONG)
			dc.B	$00,$00,$00,$00	; Group 3						(LONG)
			dc.B	$00,$00,$00,$00	; Group 4						(LONG)
			dc.B	$00,$00,$00,$00	; Group 5						(LONG)
			dc.B	$00,$00,$00,$00	; Group 6						(LONG)
			dc.B	$00,$00,$00,$00	; Group 7						(LONG)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = worm_dvc	THEN
									;
									; It is a Write-once Read-multiple Device.
									;
			dc.B	$D1,$90,$27,$BE	; Group 0						(LONG)
			dc.B	$04,$03,$10,$60	; Group 1						(LONG)
			dc.B	$00,$00,$04,$21	; Group 2						(LONG)
			dc.B	$00,$00,$00,$00	; Group 3						(LONG)
			dc.B	$00,$00,$00,$00	; Group 4						(LONG)
			dc.B	$00,$00,$00,$00	; Group 5						(LONG)
			dc.B	$00,$00,$00,$00	; Group 6						(LONG)
			dc.B	$00,$00,$00,$00	; Group 7						(LONG)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = read_dacc	THEN
									;
									; It is a Read-only Direct-Access Device.
									;
			dc.B	$D0,$90,$27,$BE	; Group 0						(LONG)
			dc.B	$04,$01,$10,$60	; Group 1						(LONG)
			dc.B	$00,$00,$04,$21	; Group 2						(LONG)
			dc.B	$00,$00,$00,$00	; Group 3						(LONG)
			dc.B	$00,$00,$00,$00	; Group 4						(LONG)
			dc.B	$00,$00,$00,$00	; Group 5						(LONG)
			dc.B	$00,$00,$00,$00	; Group 6						(LONG)
			dc.B	$00,$00,$00,$00	; Group 7						(LONG)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = scanner	THEN
									;
									; It is a Scanner Device.
									;
			dc.B	$90,$00,$27,$BC	; Group 0						(LONG)
			dc.B	$0C,$A0,$48,$78	; Group 1						(LONG)
			dc.B	$00,$0C,$04,$20	; Group 2						(LONG)
			dc.B	$00,$00,$00,$00	; Group 3						(LONG)
			dc.B	$00,$00,$00,$00	; Group 4						(LONG)
			dc.B	$00,$00,$00,$00	; Group 5						(LONG)
			dc.B	$00,$00,$00,$00	; Group 6						(LONG)
			dc.B	$00,$00,$00,$00	; Group 7						(LONG)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = optic_mem	THEN
									;
									; It is a Optical Memory Device.
									;
			dc.B	$D9,$B0,$27,$BE	; Group 0						(LONG)
			dc.B	$04,$0F,$1E,$FC	; Group 1						(LONG)
			dc.B	$00,$00,$04,$21	; Group 2						(LONG)
			dc.B	$00,$00,$00,$00	; Group 3						(LONG)
			dc.B	$00,$00,$00,$00	; Group 4						(LONG)
			dc.B	$00,$AF,$11,$04	; Group 5						(LONG)
			dc.B	$00,$00,$00,$00	; Group 6						(LONG)
			dc.B	$00,$00,$00,$00	; Group 7						(LONG)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = changer	THEN
									;
									; It is a Changer Device.
									;
			dc.B	$90,$00,$20,$8C	; Group 0						(LONG)
			dc.B	$00,$00,$00,$80	; Group 1						(LONG)
			dc.B	$00,$00,$04,$21	; Group 2						(LONG)
			dc.B	$00,$00,$00,$00	; Group 3						(LONG)
			dc.B	$00,$00,$00,$00	; Group 4						(LONG)
			dc.B	$06,$00,$00,$00	; Group 5						(LONG)
			dc.B	$00,$00,$00,$00	; Group 6						(LONG)
			dc.B	$00,$00,$00,$00	; Group 7						(LONG)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = comm_dvc	THEN
									;
									; It is a Communication Device.
									;
			dc.B	$90,$A0,$24,$2C	; Group 0						(LONG)
			dc.B	$00,$00,$00,$18	; Group 1						(LONG)
			dc.B	$00,$00,$00,$00	; Group 2						(LONG)
			dc.B	$00,$00,$00,$00	; Group 3						(LONG)
			dc.B	$00,$00,$00,$00	; Group 4						(LONG)
			dc.B	$00,$00,$00,$00	; Group 5						(LONG)
			dc.B	$00,$00,$00,$00	; Group 6						(LONG)
			dc.B	$00,$00,$00,$00	; Group 7						(LONG)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = mcd_40	THEN
									;
									; It is a Direct Access Magnetic
									; Tape Device.
									;
			dc.B	$DF,$77,$FF,$7C	; Group 0						(LONG)
			dc.B	$04,$00,$01,$18	; Group 1						(LONG)
			dc.B	$00,$00,$00,$00	; Group 2						(LONG)
			dc.B	$00,$00,$00,$00	; Group 3						(LONG)
			dc.B	$00,$00,$00,$00	; Group 4						(LONG)
			dc.B	$00,$00,$00,$00	; Group 5						(LONG)
			dc.B	$00,$00,$00,$00	; Group 6						(LONG)
			dc.B	$00,$00,$00,$00	; Group 7						(LONG)
			ENDIF

;-------------------------------------------------------------------------------

			IF		scsi_dtype = appl_laser	THEN
									;
									; It is an Apple LaserWriter Device.
									;
			dc.B	$FE,$20,$27,$20	; Group 0						(LONG)
			dc.B	$00,$00,$00,$00	; Group 1						(LONG)
			dc.B	$00,$00,$00,$00	; Group 2						(LONG)
			dc.B	$00,$00,$00,$00	; Group 3						(LONG)
			dc.B	$00,$00,$00,$00	; Group 4						(LONG)
			dc.B	$00,$00,$00,$00	; Group 5						(LONG)
			dc.B	$00,$00,$00,$00	; Group 6						(LONG)
			dc.B	$00,$00,$00,$00	; Group 7						(LONG)
			ENDIF

;-------------------------------------------------------------------------------

									;
									; SCSI Manager Call PList
									;
			dc.w	$0000			; Same as our Slot Number		(WORD)
			dc.w	scsi_dtype		; Same as our Unit Number		(WORD)			
			dc.w	$0000			; Version of call issued		(WORD)
			dc.w	$0000			; Flags from Command Table		(WORD)			
			dc.w	$0000			; Time Out Factor * xxx ms		(WORD)
									; Completion Routine Pointer	(LONG)
			dc.l	dib.complet\
					+default_dib
									; Pointer to Command Packet		(LONG)
			dc.l	dib.scsicmd\
					+default_dib			
									; Ptr to Send/R'cv Structure	(LONG)
			dc.l	dib.trx_buff\
					+default_dib
			dc.l	$00000000		; Users Send/R'cv Length		(LONG)
									; Pointer to Status Structure	(LONG)
			dc.l	auto_sense_data

			dc.l	$00000000		; Reserved space 1				(LONG)

			dc.l	$00000000		; Reserved space 2				(LONG)
									;
									; SCSI Command Packet
									;
			dcb.b	12,$00			; Room for any SCSI Command		(BYTES)
									;
									; SCSI Manager Device Send/R'cv Buffers List
									;
			dc.l	$00000000		; Users Send Buffer				(LONG)
			dc.l	$00000000		; Request cnt for this buffer	(LONG)
			dc.l	$00000000		; Offset for next pass			(LONG)
			dc.l	$00000000		; Null							(LONG)
			dc.l	$00000000		; Null							(LONG)
			dc.l	$00000000		; Null							(LONG)
			dc.l	$00000000		; Null							(LONG)
			dc.l	$00000000		; Null							(LONG)
			dcb.l	4,$00000000		; Reserved Space * 4 for future	(LONG)
									;
									; Device Busy and other Flags	(WORD)
									;
			dc.w	wait_mode++\	; Wait Mode is default
					cold_dib		; and they start cold.

									;
									; Completion Routine for this DIB.
									; This takes the remaining space in
									; the allocated RAM.  Any routine can
									; be placed here but must never go
									; beyond offset $FF
									;
			jsl		g_dib_ptr
			pei		scsi_zp0
			pei		scsi_zp1
			stx		<scsi_zp0
			sty		<scsi_zp1
			ldy		#dib.dvcflag
			lda		#int_busy--\
					$ffff
			and		[scsi_zp0],y
			sta		[scsi_zp0],y
			pla
			sta		<scsi_zp1
			pla
			sta		<scsi_zp0
			clc
			lda		#null
			rtl
@end		equ		*

;-------------------------------------------------------------------------------

			IF		@end-default_dib = dib_size	THEN
									;
									; Perfect Fit of DIB
									;
			ENDIF

;-------------------------------------------------------------------------------

			IF		@end-default_dib>dib_size	THEN
									;
									; It's too long.  Force an error
									;
			bad	 dib length
			ENDIF

;-------------------------------------------------------------------------------

			IF		@end-default_dib<dib_size	THEN
									;
									; Too Small.	 Pad to fit.
									;
			dcb.b	default_dib+$100-@end,$00
			ENDIF

;-------------------------------------------------------------------------------

			ENDP

			EJECT
			
;*******************************************************
;
;	This area contains the format options for the device
;	that this driver was written for.  It's construction
;	is as defined in the SCSI Device Driver ERS.
;
;*******************************************************

					EXPORT	format_options        
format_options		PROC

;-------------------------------------------------------------------------------

		IF		scsi_dtype = direct_acc	THEN

				EXPORT		display_cnt
				EXPORT		current_fmt
				EXPORT		opt1_blk_cnt
				EXPORT		opt1_blk_siz
				EXPORT		opt1_interleave
				EXPORT		opt1_med_siz
				EXPORT		opt2_blk_cnt
				EXPORT		opt2_blk_siz
				EXPORT		opt2_interleave
				EXPORT		opt2_med_siz
				EXPORT		opt3_blk_cnt
				EXPORT		opt3_blk_siz
				EXPORT		opt3_interleave
				EXPORT		opt3_med_siz
										;
										; Direct Access Device format options.
										;
				dc.w	$0003			;Number of entries
display_cnt		dc.w	$0002			;Number of display entries
				dc.w	$0001			;Recommended Default entry
current_fmt		dc.w	$0001			;Current Format

				dc.w	$0001			;Refnum = Option #1
				dc.w	$0002			;Linkref = Option #2
				dc.w	$0008			;Universal format
										;Size in megabytes
opt1_blk_cnt	dc.l	null			;Block Count Option #1
opt1_blk_siz	dc.w	$0200			;Block Size Option #1
opt1_interleave	dc.w	$0001			;Interleave = 1:1
opt1_med_siz	dc.w	null			;Media size in megabytes

				dc.w	$0002			;Refnum = Option #2
				dc.w	$0000			;Linkref = Option #0
				dc.w	$0008			;Universal format
										;Size in megabytes
opt2_blk_cnt	dc.l	null			;Block Count Option #2
opt2_blk_siz	dc.w	$0200			;Block Size Option #2
opt2_interleave	dc.w	$0002			;Interleave = 2:1
opt2_med_siz	dc.w	null			;Media size in megabytes
										;
										; Used only if the device is currently
										; formatted to 532 byte blocks.
										;
				dc.w	$0003			;Refnum = Option #3
				dc.w	$0000			;Linkref = Option #0
				dc.w	$0008			;Universal format
										;Size in megabytes
opt3_blk_cnt	dc.l	null			;Block Count Option #3
opt3_blk_siz	dc.w	$0214			;Block Size Option #3
opt3_interleave	dc.w	$0005			;Interleave = 5:1
opt3_med_siz	dc.w	null			;Media size in megabytes

				ENDIF

;-------------------------------------------------------------------------------

				ENDP
			
				EJECT
			
;*******************************************************
;
;	All the Data for this driver is maintained in this
;	procedure.  This is to allow easy future conversion
;	to ROM code if that is ever needed.  In order for
;	this to work, the following should be changed to a
;	RECORD structure and then the appropriate space
;	requested from the memory manager and used as a
;	temporary Direct Page space.  The template created
;	by changing this to a RECORD would then be used to
;	overlay the RAM supplied by the memory manager.
;
;*******************************************************

				EXPORT	drvrdata        
drvrdata		PROC
			
				EXPORT	direct_page
direct_page		dc.w	null				;Our Direct Page Start Address

				EXPORT	exit_dpage
exit_dpage		dc.w	null				;Our Direct Page Start Address

				EXPORT	gsos_dpage
gsos_dpage		dc.w	null				;GS/OS Direct Page Start Address

				EXPORT	valid
valid			dc.w	null				;Saved ZP Validity flag

				EXPORT	saved_zp
saved_zp		dcb.b	end_our_zp-\		;Saved GS/OS ZP Slept here
						start_our_zp,null

											;
											;Data for the GET LAST RESULT Call
											;
				EXPORT	lst_rslt_ec
				EXPORT	lst_rslt_id
				EXPORT	lst_rslt_stat
				EXPORT	lst_rslt_skey		;*** DO NOT SEPERATE THESE LABLES ***
				EXPORT	lst_rslt_info
				EXPORT	lst_rslt_rqlen
				EXPORT	lst_rslt_scode

lst_rslt_ec		dc.w	null				;GS/OS Error Code
lst_rslt_id		dc.w	null				;Device ID Number
lst_rslt_stat	dc.w	null				;Status Code
lst_rslt_skey	dc.w	null				;Sense Key
lst_rslt_info	dc.l	null				;Information Bytes
lst_rslt_rqlen	dc.w	null				;Data Length
lst_rslt_scode	dc.w	null				;Additional Sense Code

				EXPORT	master_uid
master_uid		dc.w	$0000				;Master MM User ID

				EXPORT	scsi_uid
scsi_uid		dc.w	$0000				;Our MM User ID

				EXPORT	page_cnt
page_cnt		dc.w	$0000				;Page Count for Remaining free RAM.

				EXPORT	hndl_offset
hndl_offset		dc.w	$0000				;Handle offset in new memory structure.

				EXPORT	buff_len
buff_len		dc.w	$0000				;Length of Requested Memory

				EXPORT	scratch0
scratch0		dc.w	$0000				;Scratch Working Area

				EXPORT	scratch1
scratch1		dc.w	$0000				;Scratch Working Area

				EXPORT	scratch2
scratch2		dc.w	$0000				;Scratch Working Area

				EXPORT	scratch3
scratch3		dc.w	$0000				;Scratch Working Area

				EXPORT	call_type
call_type		dc.w	$0000				;Current SCSI Command Type

				EXPORT	curr_hndl
curr_hndl		dc.l	$00000000

				EXPORT	main_caller
main_caller		dc.w	$0000

				EXPORT	ram_page_cnt
ram_page_cnt	dc.w	$0000

				EXPORT	tot_dib_cnt
tot_dib_cnt		dc.w	$0000

				EXPORT	active_starts
active_starts	dc.w	$0000
						
				EXPORT	t_dvc_blocks
t_dvc_blocks	dc.l	null				; Storage for the total block count

				EXPORT	dvc_ram				;Start of the device buffer plus
dvc_ram			dc.l	null				;the handle space

				EXPORT	sense_data
sense_data		dcb.b	one_page,null

				EXPORT	auto_sense_data
auto_sense_data	dcb.b	one_page,null

				EXPORT	format_data
				EXPORT	verify_part
verify_part
format_data		dcb.b	one_page,null

				EXPORT	dvc_count		;Number of devices returned by the
dvc_count		dc.w	null			;SCSI Manager get devices call.
										;
										; Flag to indicate whether this call
										; came as a STARTUP or a rebuild of
										; the DIBs.
										;
				EXPORT	rebuild
rebuild			dc.w	null

				EXPORT	dpi_overide
dpi_overide		dc.w	null

				EXPORT	trash_it
trash_it		dc.w	null

				EXPORT	part_num
part_num		dc.w	null

				EXPORT	vPart_cnt
vPart_cnt		dc.w	null

				EXPORT	part_cnt
part_cnt		dc.w	null

				EXPORT	first_time
first_time		dc.w	null

				EXPORT	only_one
only_one		dc.w	null

				EXPORT	result
result			dc.l	null			;Result of Divide routine

				EXPORT	divend
divend			dc.l	null			;Dividend for the division

				EXPORT	divsor
divsor			dc.w	null			;Divisor for the division

				EXPORT	max_blk_cnt
max_blk_cnt		dc.l	null			;Maximum Result allowed

				EXPORT	m_rslt
m_rslt			dc.l	null			;Result of Multiply routine

				EXPORT	m_blk_cnt
m_blk_cnt		dc.l	null			;Block Count for the Multiply

				EXPORT	m_blk_size
m_blk_size		dc.w	null			;Block Size for the Multiply

				EXPORT	timeout_flag
timeout_flag	dc.w	null			;Timeout based on block count flag

				EXPORT	time_cnt
time_cnt		dc.l	null			;Timeout Calculation Area.
										;
										; DIB Data Structure Pointer
										;
				EXPORT	dib_data_struct
dib_data_struct	dc.l	null
										;
										; Data Chaining Flag
										;
				EXPORT		uses_dc
uses_dc			dc.w	null
										;
										; Data Areas for the Main Driver.
										;
				EXPORT	f_partition
f_partition		dc.w	null			;Get the partition call flag.

				EXPORT	internal		;Internally generated command if
internal		dc.w	null			;bit 15 is set.

				EXPORT	disk_switch		;Command requires a Disk Switch if
disk_switch		dc.w	null			;bit 15 is set.

				EXPORT	scsi_mgrnum
scsi_mgrnum		dc.w	null				;SCSI Manager Number for S_DISPATCH

				EXPORT	manager_cmd
manager_cmd		dc.w	null			;SCSI Manager Command Number

				EXPORT	cur_cmd
cur_cmd			dc.w	null			;Current SCSI Command Number

				EXPORT	cur_group
cur_group		dc.w	null			;Current SCSI Command Group

				EXPORT	trans_src
trans_src		dc.w	null			;Source Command Data Offset

				EXPORT	trans_dest
trans_dest		dc.w	null			;Destination Command Data Offset

				EXPORT	p_block_num
p_block_num		dc.l	null			;Temp location for block offset.

				EXPORT	killer_blk
killer_blk		dc.l	null			;Temp location for block offset.

				EXPORT	temp_acc
temp_acc		dc.w	null			;Temporary Accumulator

				EXPORT	temp_x
temp_x			dc.w	null			;Temporary X Register

				EXPORT	temp_y
temp_y			dc.w	null			;Temporary Y Register

				EXPORT	temp_len
temp_len		dc.w	null			;Temporary Loop Length

				EXPORT	trans_flag
trans_flag		dc.w	null			;SCSI Translation Flags.

				EXPORT	new_dib
new_dib			dc.w	null			;Building a new dib flag.

				EXPORT	pdi_flag
pdi_flag		dc.w	null			;Post Driver Install is Active

				EXPORT	new_list
new_list		dc.w	null			;Post Driver List Active Flag

				EXPORT	new_dib_cnt
new_dib_cnt		dc.l	null			;Number of new devices to startup

				EXPORT	new_dib_list
										;List of DIB ptrs for the new devices
new_dib_list	dcb.l	max_partitions,0

				ENDP

				END
			
				EJECT
			
